﻿#region Using

using System;
using System.Collections.Generic;
using System.Globalization;
using System.Linq;
using Vk.Methods.Fave;
using Vk.Methods.News;
using Vk.Methods.Places;
using Vk.Methods.Users;

#endregion

namespace Vk.Methods.Groups
{
    /// <summary>
    ///     Сообщество
    /// </summary>
    public class Group : BaseGroup
    {
        private readonly ApiNode _node;

        /// <summary>
        /// Информация о занесении в черный список сообщества (поле возвращается только при запросе информации об одном сообществе).
        /// </summary>
        public BaseBanInfo BanInfo => _node.Object(GroupFields.BanInfo, apiNode => new BaseBanInfo(apiNode));

        public MemberStatus? MemberStatus => (MemberStatus?) _node.Int(GroupFields.MemberStatus);

        /// <summary>
        ///     Строка состояния публичной страницы. У групп возвращается строковое значение, открыта ли группа или нет, а у
        ///     событий дата начала.
        /// </summary>
        public string Activity => _node.String(GroupFields.Activity);

        /// <summary>
        /// Информация о том, может ли текущий пользователь написать личное сообщение сообществу.
        /// </summary>
        public bool? CanMessage => _node.Bool(GroupFields.CanMessage);

        /// <summary>
        ///     Информация о том, может ли текущий пользователь создать тему обсуждения в группе, используя метод board.addTopic.
        /// </summary>
        public bool? CanCreateTopic => _node.Bool(GroupFields.CanCreateTopic);

        /// <summary>
        ///     Информация о том, может ли текущий пользователь оставлять записи на стене сообщества.
        /// </summary>
        public bool? CanPost => _node.Bool(GroupFields.CanPost);

        /// <summary>
        ///     Информация о том, разрешено видеть чужие записи на стене группы.
        /// </summary>
        public bool? CanSeeAllPosts => _node.Bool(GroupFields.CanSeeAllPosts);

        /// <summary>
        ///     Информация о том, может ли текущий пользователь загружать документы в группу.
        /// </summary>
        public bool? CanUploadDoc => _node.Bool(GroupFields.CanUploadDoc);

        /// <summary>
        /// Информация о том, может ли текущий пользователь загружать видеозаписи в группу. 
        /// </summary>
        public bool? CanUploadVideo => _node.Bool(GroupFields.CanUploadVideo);

        /// <summary>
        ///     Идентификатор города, указанного в информации о сообществе.
        /// </summary>
        public int? City => _node.Int(GroupFields.City);

        /// <summary>
        ///     Информация из блока контактов публичной страницы.
        /// </summary>
        public List<PageContact> Contacts
            => _node.SelectNode(GroupFields.Contacts).ChildNodes.Select(x => new PageContact(x)).ToList();

        /// <summary>
        ///     Объект counters, содержащий счётчики сообщества, может включать любой набор из следующих полей: photos, albums,
        ///     audios, videos, topics, docs.
        /// </summary>
        /// <remarks>Поле возвращается только при запросе данных об одном сообществе</remarks>
        public GroupCounters Counters => _node.Object(GroupFields.Counters, apiNode => new GroupCounters(apiNode));

        /// <summary>
        ///     Идентификатор страны, указанной в информации о сообществе.
        /// </summary>
        public int? Country => _node.Int(GroupFields.Country);

        /// <summary>
        ///     Текст описания сообщества
        /// </summary>
        public string Description => _node.String(GroupFields.Description);

        /// <summary>
        ///     Время окончания встречи
        /// </summary>
        public DateTime? FinishDate => _node.DateTime(GroupFields.FinishDate);

        /// <summary>
        /// Информация о том, находится ли сообщество в закладках у текущего пользователя.
        /// </summary>
        public bool? IsFavorite => _node.Bool(GroupFields.IsFavorite);

        /// <summary>
        /// Информация о том, скрыто ли сообщество из ленты новостей текущего пользователя.
        /// </summary>
        public bool? IsHiddenFromFeed => _node.Bool(GroupFields.IsHiddenFromFeed);

        /// <summary>
        /// Возвращается для публичных страниц.Текст описания для поля start_date.
        /// </summary>
        public string PublicDateLabel => _node.String(GroupFields.PublicDateLabel);

        /// <summary>
        ///     Идентификатор post_id закрепленного поста сообщества. Сам пост можно получить, используя wall.getById, передав в
        ///     поле posts – {group_id}_{post_id}.
        /// </summary>
        public int? FixedPost => _node.Int(GroupFields.FixedPost);

        /// <summary>
        ///     Информация из блока ссылок сообщества.
        /// </summary>
        public List<GroupLinkInfo> Links => _node.SelectNode(GroupFields.Links).ChildNodes.Select(x => new GroupLinkInfo(x)).ToList();

        /// <summary>
        /// Информация о главной секции в сообществе.
        /// </summary>
        public MainSection? MainSection => (MainSection?) _node.Int(GroupFields.MainSection);

        /// <summary>
        /// Идентификатор основного фотоальбома сообщества.
        /// </summary>
        public int? MainAlbumId => _node.Int(GroupFields.MainAlbumId);

        //TODO: Market property

        /// <summary>
        ///     Количество участников сообщества
        /// </summary>
        public int? MembersCount => _node.Int(GroupFields.MembersCount);

        /// <summary>
        ///     Место, указанное в информации о сообществе
        /// </summary>
        public Place Place => _node.Object(GroupFields.Place, apiNode => new Place(apiNode));

        /// <summary>
        ///     Адрес сайта из поля «веб-сайт» в описании сообщества.
        /// </summary>
        public string Site => _node.String(GroupFields.Site);

        /// <summary>
        ///     Время начала встречи (для событий) или дата основания для публичных страниц
        /// </summary>
        public DateTime? StartDate
        {
            get
            {
                switch (Type)
                {
                    case GroupType.Page: //For example, 20130115
                        var str = _node.String(GroupFields.StartDate);
                        return str != null
                                   ? (DateTime?) DateTime.ParseExact(str, "yyyyMMdd", CultureInfo.InvariantCulture)
                                   : null;
                    case GroupType.Event: //For example, 1270200630 - unixtime
                        return _node.DateTime(GroupFields.StartDate);
                    default:
                        return null;
                }
                
            }
        }

        /// <summary>
        ///     Статус сообщества. Возвращается строка, содержащая текст статуса, расположенного на странице сообщества под его
        ///     названием.
        /// </summary>
        public string Status => _node.String(GroupFields.Status);

        /// <summary>
        ///     Возвращает информацию о том, является ли сообщество верифицированным.
        /// </summary>
        public bool? Verified => _node.Bool(GroupFields.Verified);

        /// <summary>
        ///     Название главной вики-страницы сообщества
        /// </summary>
        public string WikiPage => _node.String(GroupFields.WikiPage);

        /// <summary>
        /// Возрастное ограничение.
        /// </summary>
        public AgeLimit? AgeLimits => (AgeLimit?)_node.Int(GroupFields.AgeLimits);

        public Group(ApiNode node) : base(node)
        {
            _node = node;
        }
    }
}